#pragma once
#include <list>
#include <vector>
#include <string>
#include <map>
#include <memory>
#include <assert.h>
#include "config.h"
#if defined _DEBUG
#define RE_NEW new(_NORMAL_BLOCK,__FILE__, __LINE__) 
#else
#define RE_NEW new
#endif
#include "RELogger.h"
#include "General Stuff\BaseVariables.h"
#include "Geometry.h"
#include "REString.h"
#include "General Stuff\PathTools.h"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------------------------------------------//
//RandomEngineApp and Logic interfaces
//-----------------------------------------------------------------------------------------------------------------//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------------------------------------------
//Game View Interface. Used as "character controllers"
//-------------------------------------------------------------------------------------------------------
class IGameView;
typedef std::tr1::shared_ptr< IGameView > GameViewPtr;
typedef std::list< GameViewPtr > GameViewList;
typedef unsigned int ActorId;
class IGameView
{
public:
	explicit IGameView(){};
	virtual ~IGameView(){};

	virtual void VOnRender() = 0;
	virtual void VOnUpdate(float fTime) = 0;
	virtual ActorId VGetActorId() = 0;
	virtual void VSetActorId(ActorId id) = 0;
};
//-------------------------------------------------------------------------------------------------------
//Controller. Checks input and do the required actions.
//-------------------------------------------------------------------------------------------------------
class IInputMap;
typedef std::tr1::shared_ptr<IInputMap> InputMapPtr;
typedef RE_String GameAction;
class IInputMap
{
public:
	IInputMap() {}
	~IInputMap() {}

	virtual bool VIsTrue(const GameAction action) = 0;
	virtual void VKeyDown(const unsigned char key) = 0;
	virtual void VKeyUp(const unsigned char key) = 0;
	virtual void VSetActionKey(const GameAction action, const unsigned char key) = 0;
	virtual void VResetActionMap() = 0;
	virtual GameAction VIsActionMapped(const unsigned char key) = 0;
};
//-------------------------------------------------------------------------------------------------------
//Controller. Checks input and do the required actions.
//-------------------------------------------------------------------------------------------------------
class IController;
typedef std::tr1::shared_ptr<IController> ControllerPtr;
typedef std::list<ControllerPtr> ControllerList;
class IController
{
public:
	IController() {}
	~IController() {}

	virtual void VOnActionDown(GameAction action) = 0;
	virtual void VOnActionUp(GameAction action) = 0;
	virtual void VOnUpdate() = 0;
	virtual IInputMap* VGetInputMap() = 0;

};

//-------------------------------------------------------------------------------------------------------
//Screen Element Interface. Scene is screen element(it takes place of the screen), HUD, etc..
//-------------------------------------------------------------------------------------------------------
class IScreenElement;
typedef std::tr1::shared_ptr< IScreenElement > ScreenElementPtr;
typedef std::list< ScreenElementPtr > ScreenElementList;
class IScreenElement
{
public:
	explicit IScreenElement(){};
	virtual ~IScreenElement(){};

	virtual bool VOnUpdate(float fTime) = 0;
	virtual bool VOnRender() = 0;

};
//-------------------------------------------------------------------------------------------------------
//Actor Component. The interface that actually add functionality to the actor.
//-------------------------------------------------------------------------------------------------------
class IActorComponent;
typedef std::tr1::shared_ptr<IActorComponent> ActorComponentPtr;
typedef std::list < ActorComponentPtr > ActorComponentList;
typedef RE_String ComponentType;
class IActorComponent
{
public:
	IActorComponent() {}
	~IActorComponent() {}

	virtual const ComponentType & VGetComponentType() = 0;
	virtual const ComponentType & VGetBaseComponentType() = 0;
	virtual bool VOnUpdate(float fTime) = 0;

};
//-------------------------------------------------------------------------------------------------------
//Actor Interface. Actor is logic's representation of an object living in the virtual world.
//-------------------------------------------------------------------------------------------------------
class IActor;
typedef std::tr1::shared_ptr< IActor > ActorPtr;
typedef std::list< ActorPtr > ActorList;
typedef std::map < ActorId, ActorPtr > ActorMap;
class IActor
{
public:
	explicit IActor() {}
	virtual ~IActor() {}

	virtual bool VAddComponent(ActorComponentPtr ActorComponent) = 0;
	virtual bool VRemoveComponent() = 0;

	template<class T>
	T* GetComponent(const ComponentType type) {
		ActorComponentPtr cmp = FindComponent(type);
		if(cmp == ActorComponentPtr())
		{
			assert(0 && "Component not found");
			return NULL;
		}
		return dynamic_cast<T*>(cmp.get());
	};
	virtual ActorComponentPtr FindComponent(const ComponentType) = 0;
	virtual bool VOnUpdate(float fTime) = 0;
	virtual const ActorId VGetId() = 0;
	virtual void VSetId(ActorId id) = 0;
};
//-------------------------------------------------------------------------------------------------------
//Game Logic Interface. Manages actors and applies game logic.
//-------------------------------------------------------------------------------------------------------
class IGameLogic;
typedef std::tr1::shared_ptr< IGameLogic > LogicPtr;
class IAssetData;
typedef std::tr1::shared_ptr< IAssetData > AssetDataPtr;
typedef std::tr1::weak_ptr< IAssetData > AssetDataWeakPtr;
class IEventData;
typedef std::tr1::shared_ptr< IEventData > EventDataPtr;
class IGameLogic
{
public:
	explicit IGameLogic() {};
	virtual ~IGameLogic() {};

	virtual void VAddView(GameViewPtr view) = 0;
	virtual void VRemoveView(GameViewPtr view) = 0;

	virtual void VAddActor(ActorPtr actor) = 0;
	virtual ActorId VGenerateActorId() = 0;
	virtual void VRemoveActor(const ActorId id) = 0;
	virtual void VMoveActor(const ActorId id, const Vec3 & dir) = 0;
	virtual ActorPtr VGetActor(const ActorId id) = 0;

	virtual void VOnRender() = 0;
	virtual void VOnUpdate(float fTime) = 0;
	virtual void VHandleEvent(EventDataPtr EventData) = 0;

	virtual bool VBuildInitialScene() = 0;
	virtual bool VLoadScene(AssetDataPtr level) = 0;
	virtual bool VClearScene() = 0;
};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------------------------------------------//
//Event Manager Interfaces.
//-----------------------------------------------------------------------------------------------------------------//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------------------------------------------
//Event Data Interface. "Container" for event information.
//-------------------------------------------------------------------------------------------------------
typedef RE_String EventType;
//EventTypeMap -> In event listener
class IEventData
{
public:
	explicit IEventData() {};
	virtual ~IEventData() {};

	virtual const EventType VGetEventType() = 0;
	template<class T>
	T* GetData() { return dynamic_cast<T*>(this); }
};
//-------------------------------------------------------------------------------------------------------
//Event Listener Interface. This class just receives events and then "executes" them.
//-------------------------------------------------------------------------------------------------------
class IEventListener;
typedef std::tr1::shared_ptr< IEventListener > EventListenerPtr;
typedef std::list<EventListenerPtr> EventListenerList;
typedef std::map<EventType, EventListenerList> EventTypeMap;
class IEventListener
{
public:
	explicit IEventListener() {};
	virtual ~IEventListener() {};

	virtual void HandleEvent(EventDataPtr EventData) = 0;
	bool operator == (IEventListener & param)
	 {
		 if(&(*this) == &(param)) // cmp addresses
		 {
			 return true;
		 }
		 else
		 {
			 return false;
		 }
	 }
};
//-------------------------------------------------------------------------------------------------------
//Event Manager Interface. It take care of sending messages to the right listeners.
//-------------------------------------------------------------------------------------------------------
class IEventManager;
typedef std::tr1::shared_ptr< IEventManager > EventManagerPtr;
class IEventManager
{
public:
	explicit IEventManager() {};
	virtual ~IEventManager() {};

	virtual void VAddListener(EventListenerPtr listener, EventType evt_type) = 0;
	virtual void VRemoveListener(EventListenerPtr listener, EventType evt_type) = 0;
	virtual void VRemoveListener(EventListenerPtr listener) = 0;
	virtual bool VValidateEventType(const EventType & evt) = 0;

	virtual void VTriggerEvent(EventDataPtr eventData) = 0;
	virtual void VQueEvent(EventDataPtr eventData) = 0;
	virtual void VRemoveLastEventFromQueue() = 0;
	virtual void VTick() = 0;
};


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------------------------------------------//
//Resource Cache Interfaces
//-----------------------------------------------------------------------------------------------------------------//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



//-------------------------------------------------------------------------------------------------------
//Resource File Interface. Used to open certain file format and load its content.
//-------------------------------------------------------------------------------------------------------
class IResourceFile;
typedef std::tr1::shared_ptr<IResourceFile> ResourceFilePtr;
typedef std::list<ResourceFilePtr> ResourceFileList;
typedef std::map< RE::IO::FilePath ,ResourceFilePtr > ResourceFileMap;
class IResourceFile
{
public:
	IResourceFile() {}
	~IResourceFile() {}
public:

	virtual bool VOpen() = 0;
	virtual const std::string VGetFilename() = 0;
	virtual unsigned int VGetResourceSize(const RE::IO::FilePath & res) = 0;
	virtual void VGetResource( const RE::IO::FilePath & res, char * buffer) = 0;
	virtual bool VFileExist(const std::string & filename) = 0;
};
//-------------------------------------------------------------------------------------------------------
//Resource Handle Interface. Contains the data itself.
//-------------------------------------------------------------------------------------------------------
class IResHandle;
class IResCache;
typedef std::tr1::shared_ptr<IResHandle> ResHandlePtr;
typedef std::list<ResHandlePtr> ResHandleList;
typedef std::multimap< unsigned int, std::pair< std::string, ResHandlePtr >	> ResHandleMap;

class IResHandle
{
	friend IResCache;
public:
	IResHandle() {}
	~IResHandle() {}

	virtual unsigned int VGetSize() = 0;
	virtual char* VGetBuffer() = 0;
	virtual const RE::IO::FilePath& VGetResource() = 0;
};
//-------------------------------------------------------------------------------------------------------
//Resource Cache Interface. Manages the resources and their handles.
//-------------------------------------------------------------------------------------------------------
typedef std::tr1::shared_ptr<IResCache> ResCachePtr;
class IResCache
{
public:
	friend IResHandle;
	IResCache() {}
	~IResCache() {}
	//ResourceHandle & Holder Managment
	virtual ResHandlePtr	VGetHandle(const RE::IO::FilePath &res) = 0;

	//ResourceFile Managment
	virtual unsigned int VAddResourceFile(RE::IO::FilePath & path, ResourceFilePtr ResFile) = 0; // if return 0 -> something went wrong
	virtual bool VRemoveResourceFile(RE::IO::FilePath& path, bool RemoveHandles) = 0;
	virtual unsigned int VGetResFileIdByFileName(const std::string & str) = 0;

	//Cache Managment
	virtual void VSetBytesCap(unsigned int bytes) = 0;
	virtual unsigned int VGetBytesCap() = 0;
	virtual unsigned int VGetUsedBytes() = 0;
	virtual void VFreeMemory(unsigned int bytes) = 0;

	virtual void VBytesAllocated(const unsigned int bytes) = 0;
	virtual void VBytesReleased(const unsigned int bytes) = 0;
};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------------------------------------------//
//Scene Graph Interfaces.
//-----------------------------------------------------------------------------------------------------------------//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------------------------------------------
//Scene Node Interface. Scene's object representing visible part of the world.
//-------------------------------------------------------------------------------------------------------
class IScene;
class ISceneNode;
typedef std::tr1::shared_ptr<ISceneNode> SceneNodePtr;
typedef std::tr1::weak_ptr<ISceneNode> SceneNodeWeakPtr;
typedef std::list<SceneNodePtr> SceneNodeList;
class ISceneNode
{
public:
	explicit ISceneNode() {}
	virtual ~ISceneNode() {}

	virtual SceneNodeList& VGetChildren() = 0;
	virtual bool VOnRender(IScene * pScene) = 0;
	virtual bool VPreRender(IScene * pScene) = 0;
	virtual bool VPostRender(IScene * pScene) = 0;
	virtual bool VOnUpdate(float fTime) = 0;
	virtual bool VRenderChildren(IScene *pScene) = 0;
	virtual bool VAddChild(SceneNodePtr scene_node) = 0;
	virtual bool VIsVisible() = 0;
	virtual ActorId VGetId() = 0;
};
//-------------------------------------------------------------------------------------------------------
//Scene Graph. Responible for rootscene node and frustum culling(matrix stack also)
//-------------------------------------------------------------------------------------------------------
class RootSceneNode;
typedef std::tr1::shared_ptr<IScene> ScenePtr;
typedef std::map<ActorId, SceneNodePtr> SceneNodeMap;
class IScene
{
public:
	explicit IScene() {}
	virtual ~IScene() {}
		
	virtual bool VOnRender() = 0;
	virtual bool VOnUpdate(float fTime) = 0;
	virtual void VBuildAndSetViewMatrix(const Vec3 & Position = Vec3(0,0,0), const Vec3 & LookAt = Vec3(1,0,1), const Vec3 & WorldUpVector = Vec3(0,1,0)) = 0;
	virtual void VBuildAndSetProjMatrix(float FOV = D3DX_PI / 4, float AspectRatio = 1.0f, float ClippingPlane_near = 1.0f, float ClippingPlane_far = 100.0f) = 0;
	virtual void VPushAndSetMatrix(const Mat4x4 & ToWorld) = 0;
	virtual void VPopMatrix() = 0;
	virtual SceneNodePtr VGetRootSceneNode() = 0;
	virtual ISceneNode* VGetNodeById(const ActorId id) = 0;
	virtual void VAddSceneNode(const SceneNodePtr node) = 0;
};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------------------------------------------//
//AssetManager Interfaces. Taking care of importing data.
//-----------------------------------------------------------------------------------------------------------------//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------------------------------------------
//AssetData interface. Containing the already imported data.
//-------------------------------------------------------------------------------------------------------
typedef std::list<AssetDataPtr> AssetDataList;
typedef RE_String AssetType;
class IAssetData
{
public:
	IAssetData() {}
	~IAssetData() {}
	virtual const AssetType & GetAssetType() = 0;
	virtual AssetDataPtr GetParent() = 0;
	virtual void SetParent(AssetDataPtr parent) = 0;
	virtual void AddChild(AssetDataPtr child) = 0;
	virtual const RE_String GetName() = 0;
	virtual AssetDataPtr TraceParent(const AssetType & type) = 0;

	virtual bool Restore() = 0; // basically, making sure the asset data is loaded and ready for use
	virtual bool RestoreChildren() = 0;
	virtual bool Release() = 0;
	virtual void RemoveChildren() = 0;
	virtual AssetDataList GetChildrenByType(const AssetType & type) = 0;
};

//-------------------------------------------------------------------------------------------------------
//Asset Parser Interface. Imports the data to asset data structures.
//-------------------------------------------------------------------------------------------------------
class IAssetParser;
typedef std::tr1::shared_ptr<IAssetParser> AssetParserPtr;
typedef std::list<AssetParserPtr> AssetParserList;
typedef std::map< RE::IO::FilePath , AssetDataList > ResourceMap;
typedef std::multimap< RE_String , AssetDataPtr > AssetNameMap;
typedef std::map< std::string, AssetParserPtr > ParserMap;
class IAssetParser
{
public:
	IAssetParser() {}
	~IAssetParser() {}

	virtual AssetDataList & VLoad(RE::IO::FilePath & res, char * bfr, unsigned int sze ) = 0;
	virtual AssetDataList & VGetData() = 0;
	virtual void VBegin() = 0;
	virtual void VEnd() = 0;
};

//-------------------------------------------------------------------------------------------------------
//Asset Manager Interface.
//-------------------------------------------------------------------------------------------------------
class IAssetManager;
typedef std::tr1::shared_ptr<IAssetManager> AssetManagerPtr;
class IAssetManager
{
public:
	IAssetManager() {}
	~IAssetManager() {}

	virtual AssetDataList * GetAssetData(RE::IO::FilePath &res) = 0;
	virtual AssetDataPtr GetAssetData(const std::string & node_name) = 0;
	virtual AssetDataPtr GetAssetData(const RE_String & node_name) = 0;
	virtual void AddAsset(RE::IO::FilePath & res, AssetDataList * assets) = 0;
	virtual void RestoreAssets() = 0;
	virtual void ReleaseAssets(const bool OnlyBuffers = true) = 0;
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------------------------------------------//
//Renderer Interfaces.
//-----------------------------------------------------------------------------------------------------------------//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------------------------------------------
//Renderer Interface. Main rendering interface.
//-------------------------------------------------------------------------------------------------------
class RE_Mesh; class RE_Texture; class RE_Material; class RE_Effect;
class IRenderer;
typedef std::tr1::shared_ptr<IRenderer> RendererPtr;
enum RE_DEVSTATE
{
	RE_OK, //device is working property
	RE_LOST, // device is lost, wait until it is in reset mode
	RE_RESET, // device is in reset mode. It can be reset if used resources are feed.
	RE_ERROR // unknown error

};
class IRenderer
{
public:
	IRenderer() {}
	~IRenderer() {}
//-----------------------------------------------------------------------------------------------------------------
//Device Functions
//-----------------------------------------------------------------------------------------------------------------
	virtual void VValidateDevice(unsigned long num_passes) = 0;
	virtual void VBeginScene() = 0;
	virtual void VEndScene() = 0;
	virtual void VShowCursor(const bool show_cursor) = 0;
	virtual void VResetDeviceState(U32 width, U32 height) = 0;
	virtual bool VPresentBackBuffer() = 0;
	virtual RE_DEVSTATE VRequestState() = 0;
//-----------------------------------------------------------------------------------------------------------------
//Buffer Functions
//-----------------------------------------------------------------------------------------------------------------
	virtual void VDrawMesh(RE_Mesh * mesh) = 0;
	virtual void VUpdateIndexBuffer(RE_Mesh * mesh) =0;
	virtual void VUpdateVertexBuffer(RE_Mesh * mesh) =0;
	virtual bool VReleaseBuffers(RE_Mesh * mesh) = 0;
	virtual void VSetSamplerState() = 0;
//-----------------------------------------------------------------------------------------------------------------
//Matrix States
//-----------------------------------------------------------------------------------------------------------------
	virtual void VSetWorldMatrix(const Mat4x4 * const world) = 0;
	virtual const Mat4x4* VGetWorldMatrix() = 0;
	virtual void VSetViewMatrix(const Mat4x4 * const view) = 0;
	virtual const Mat4x4* VGetViewMatrix() = 0;
	virtual void VSetProjMatrix(const Mat4x4 * const proj) = 0;
	virtual const Mat4x4* VGetProjMatrix() = 0;
//-----------------------------------------------------------------------------------------------------------------
//Material States
//-----------------------------------------------------------------------------------------------------------------
	virtual void VSetMaterial(RE_Material * mat) = 0;
	virtual RE_Material* const VGetMaterial() = 0;

	virtual void VCreateEffect(RE_Effect * effect) = 0;
	virtual void VSetEffect(RE_Effect * effect) = 0;
	virtual RE_Effect* VGetEffect() = 0;
	virtual void VReleaseEffect(RE_Effect * effect) = 0;


	virtual void VSetDeclaration(D3DVERTEXELEMENT9 * vd) = 0;
	virtual D3DVERTEXELEMENT9* VGetDeclaration() = 0;

	virtual void VCreatePixelShader() = 0;
	virtual void VCreateVertexShader() = 0;
	virtual void VSetPixelShader() = 0;
	virtual void VGetPixelShader() = 0;
	virtual void VSetVertexShader() = 0;
	virtual void VGetVertexShader() = 0;
//-----------------------------------------------------------------------------------------------------------------
//Render Targets And Surfaces
//-----------------------------------------------------------------------------------------------------------------
	virtual void VClear() = 0;
	virtual void VSetColorFill() = 0;
	virtual void TakeScreenshot(std::wstring location) = 0;
	virtual void VCreateAdditionalSwapChain() = 0;
	virtual void VCreateCubeTextureSurface() = 0;
	virtual void VCreateDepthStencilSurface() = 0;
	virtual void VCreateOffscreenPlainSurface() = 0;
	virtual void VCreateRenderTarget() = 0; 
	virtual void VUpdateSurface() = 0; // copy portion of one texture to another
	virtual void VStretchRectangle() = 0;
//-----------------------------------------------------------------------------------------------------------------
//Textures
//-----------------------------------------------------------------------------------------------------------------
	virtual void VUpdateTexture(RE_Texture * texture) = 0; // uses asset data of type texture to form D3DTexture object
	virtual void VReleaseTexture(RE_Texture * texture) = 0;
	virtual void VSetTexture( RE_Texture * texture) = 0;
};


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------------------------------------------//
//OS Framework interface.
//-----------------------------------------------------------------------------------------------------------------//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
enum RE_RENDERER
{
	RER_D3D9,
	//RER_D3D11,
	//RER_OPENGL,
	RER_NULL
};
class IOSFramework;
typedef std::tr1::shared_ptr<IOSFramework> OSFrameworkPtr;
typedef std::tr1::weak_ptr<IOSFramework> OSFrameworkWeakPtr;
class __single_inheritance RandomEngineApp;

typedef  bool (RandomEngineApp:: *rndengine_bool_float_func)(float);
typedef  void (RandomEngineApp:: *rndengine_void_void_func)(void);
IOSFramework * g_OSFramework; // global instance of the current framework
class IOSFramework // singleton(but not keeped globally, just global pointer because of the GetAppDir func)
{
public:
	IOSFramework() { g_OSFramework = this; }
	~IOSFramework() { g_OSFramework = 0; }

	//general purpose funcs

	virtual const std::wstring& GetApplicationDir() = 0;

	//OS Framework

	virtual void VInitialize(U32 width, U32 height, TCHAR* title, RE_RENDERER renderer_type) = 0;
	virtual void VCreateMainWindow(U32 width, U32 height, TCHAR* title) = 0;
	virtual IRenderer* VCreateRenderer(RE_RENDERER renderer_type) = 0;
	virtual void VRun() = 0;
	virtual void VShutDown() = 0;



	//set Callbacks
	virtual void SetRandomEngineObject(RandomEngineApp * app) = 0;
	virtual void SetUpdateCallback(rndengine_bool_float_func updateclb) = 0;
	virtual void SetRenderCallback(rndengine_bool_float_func renderclb) = 0;
	virtual void SetCreateDeviceCallback(rndengine_void_void_func createclb) = 0;
	virtual void SetDestroyDeviceCallback(rndengine_void_void_func destroyclb) = 0;
	virtual void SetResetDeviceCallback(rndengine_void_void_func resetclb) = 0;
	virtual void SetLostDeviceCallback(rndengine_void_void_func lostclb) = 0;
};